﻿using System;
using System.Net;
using System.Xml;
//4.5.3 抛出异常
// 可以在运行时或用户代码中抛出异常。

namespace _105_try语句和异常_抛出异常
{
    class Test
    {
        //下面的例子中Display方法抛出System.ArgumentNullException异常：
        static void Display(string name)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            Console.WriteLine(name);
        }
        static void Main(string[] args)
        {
            try { Display(null); }
            catch (ArgumentNullException ex)
            {
                Console.WriteLine("Caught the exception");
            }
            
            

            // 重新抛出异常
            // 可以捕获异常后再重新抛出，如下：
            /*
            try { }
            catch (Exception ex)
            {
                // 记录错误
                // ...
                throw; // 重新抛出同一个异常
            }
            */
            //提示：如果将throw替换为throw ex，那么这个例子仍然有效，但是新产生异常的StackTrace属性不再反映原始的错误。

            //此处的重新抛出异常，使记录错误后，异常不会被删除。它还可以用于取消对本应在外部处理的异常的内部处理：
            //using System.Net;
            string s = null;
            using(WebClient wc = new WebClient())
            {
                try { s = wc.DownloadString("http://www.albahari.com/nutshell/"); }
                catch(WebException ex)
                {
                    if (ex.Status == WebExceptionStatus.NameResolutionFailure)
                        Console.WriteLine("Bad domain name");
                    else
                        throw; // 不能处理其他种类的WebException，所以重新抛出
                }
            }

            // 另一种常见情形是，重新抛出某个明确的异常类型，例如：
            try
            {
                //... // 从XML元数据中解析出DataTime值
            }
            catch(FormatException ex)
            {
                throw new XmlException("Invalid DataTime",ex);
            }
            //重新抛出异常不会影响的StackTrace属性。当重新抛出一个不同类型的异常时，可以设置InnerException属性为原始的异常，这样有利于调试。几乎所有类型的异常都可以实现这一目的。

            Console.ReadKey();
        }
    }
}
// 4.5.4 System.Exception的关键属性
//System.Exception类的最重要的属性有下面几个：
//StackTrace
//    表示从异常的起源到catch块的所有方法的字符串
//Message
//    描述异常的字符串
//InnerException
//    导致外部异常的内部异常（如果有的话）。它本身还可能有另一个InnerException。
//提示：所有的C#异常都是运行时异常，没有和Java对等的编译时检查异常。